package com.jackwoo.jerrymouse.http;

import com.jackwoo.jerrymouse.classloader.WebAppClassLoader;
import com.jackwoo.jerrymouse.threads.HttpServerThread;
import com.jackwoo.jerrymouse.util.FileUtil;
import com.jackwoo.jerrymouse.util.MagicNumberUtil;
import com.jackwoo.jerrymouse.util.SysStaticResGenerator;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Author: StupidZhe
 * Date: 2019/11/19
 * Desc: HttpServer代表一个服务
 **/
public class HttpServer extends AbstractHttpServer {

    public static class ParseResult {
        public ParseResult() {
        }

        public ParseResult(byte[] content) {
            this.content = content;
        }

        // 解析内容
        public byte[] content;

        // 类型（"png"、"jpg"等）
        public MagicNumberUtil.TYPES contentType;
    }



    // 路由-静态资源映射表
    private Map<String, File> routerStaticResourceMap = new ConcurrentHashMap<>(50);

    // 路由-servlet映射表
    private Map<String, File> routerServletResourceMap = new ConcurrentHashMap<>(50);
    private Map<String, Object> routerServletMap = new ConcurrentHashMap<>(50);

    // 静态资源-解析结果映射表
    private Map<String, HttpServer.ParseResult> staticResourceContentMap = new ConcurrentHashMap<>(50);


    // 服务本地根路径
    private final String webRoot;

    //httpServer名称，为根路径包名
    private final String name;

    // 每个HttpServlet
    private final WebAppClassLoader webAppClassLoader = new WebAppClassLoader();
    private ConcurrentHashMap<String, Object> servletMap = new ConcurrentHashMap<>(40);

    public HttpServer(String webRoot) throws IOException {
        this.webRoot = webRoot;
        String[] s = webRoot.split(File.separator);
        name = s[s.length - 1];
//        Map<String, String> clazz;
//        clazz = resolveJsp(webRoot);
//        for (Map.Entry<String, String> e : clazz.entrySet()) {
//            try {
//                Class servletClass = webAppClassLoader.loadClass(e.getValue());
//                Object servlet = servletClass.getConstructor().newInstance();
//                servletMap.put(e.getKey(), servlet);
//            } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) {
//                ex.printStackTrace();
//            }
//        }
    }

    @Override
    public void process(Request request, Socket client) throws IOException {
        // 解析
        HttpServer.ParseResult parseResult = parseUri(request.getRouter(), request);

        // 生成response
        Response response = new Response(parseResult, 200);

        // 输出response
        sendResponse(response, client);

        // 关闭socket
        closeSocket(client);
    }

    private Map<String, String> resolveJsp(String webRoot) throws IOException {
        Map<String, String> jspMap = FileUtil.jspScan(webRoot);
        return jspMap;
    }
    // 解析uri
    // 获取静态文件
    public HttpServer.ParseResult parseUri(String router, Request request) throws IOException {

        String[] s = router.split("/" + getName());
        String fileName = s[1];


        File file = new File(getWebRoot() + File.separator + fileName);
        HttpServer.ParseResult parseResult = null;
        if (file.exists()) {
            // 静态文件处理
            parseResult = parseStaticRes(file, request);
        } else {

            // servlet处理
            File servletFile = new File(getWebRoot() + File.separator + fileName + ".class");
            if (!servletFile.exists()) {
                // 如果不存在直接返回404
                throw new IOException();
            }
            parseServletClass(servletFile, request);



        }
        return parseResult;
    }

    private void parseServletClass(File servletFile, Request request) throws IOException {
        String router = request.getRouter();
        File lastServletFile = routerServletResourceMap.get(router);
        byte[] content;
        if (lastServletFile != null) {
            if (lastServletFile.lastModified() != servletFile.lastModified()) {
                // update
                routerServletResourceMap.put(router, lastServletFile);
                content = FileUtil.getContent1(lastServletFile);

            } else {

            }
        } else {
            content = FileUtil.getContent1(servletFile);

            // 判断文件类型是否为class文件
            MagicNumberUtil.TYPES contentType = MagicNumberUtil.getFileType(content);
            if (MagicNumberUtil.TYPES.clazz == contentType) {
                routerServletResourceMap.put(router, servletFile);
                
            } else {
                return;
            }
        }
    }

    /**
     * 处理静态资源
     *
     * @param file 文件对象
     * @return
     * @throws IOException
     */
    private HttpServer.ParseResult parseStaticRes(File file, Request request) throws IOException {
        String router = request.getRouter();
        byte[] content;
        HttpServer.ParseResult parseResult = new HttpServer.ParseResult();
//        parseResult.content = content;
//        parseResult.contentType = file.

        // 获取
        File lastFile = routerStaticResourceMap.get(router);
        if (lastFile != null) {
            if (lastFile.lastModified() != file.lastModified()) {
                // update
                routerStaticResourceMap.put(router, lastFile);
                content = FileUtil.getContent1(lastFile);
                parseResult.content = content;
                // update
                staticResourceContentMap.put(router, parseResult);
            } else {
                parseResult = staticResourceContentMap.get(router);
            }
        } else {
            content = FileUtil.getContent1(file);


            routerStaticResourceMap.put(router, file);

            // 获取内容
            parseResult.content = content;

            // 获取文件类型
            parseResult.contentType = MagicNumberUtil.getFileType(content);
            staticResourceContentMap.put(router, parseResult);
        }
        return parseResult;
    }


    private void sendResponse(Response response, Socket client) throws IOException {

        BufferedOutputStream writer = new BufferedOutputStream(client.getOutputStream());
        writer.write(response.getBytes());
//            {
//                BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(new File("/Users/StupidZhe/IT/JerryMouse/web-root/test/test")));
//                stream.write(response.getBytes());
//                stream.flush();
//                stream.close();
//            }
        writer.flush();
        writer.close();
    }


    private void closeSocket(Socket socket) throws IOException {
        socket.close();
    }


    public String getWebRoot() {
        return webRoot;
    }

    public String getName() {
        return name;
    }
}
